import { Quaternion, Vector3 } from 'three';
import { KongZhi } from './KongZhi.js'
import { sheZhi } from '../cunChu/bianLiang.js'
import { huanJing } from '../huanJing/HuanJing.js'
import { gengXinJiHe } from '../gengXin/gengXin.js'

// 自由视角默认快捷键
let moRenKuaiJieJian = {
	yiSuZeng: {
		miaoShu: '移速增',
		kuaiJieJian: 'ShiftLeft'
	},
	yiSuJian: {
		miaoShu: '移速减',
		kuaiJieJian: 'ShiftRight'
	},
	qianJin: {
		miaoShu: '前进',
		kuaiJieJian: 'KeyW'
	},
	houTui: {
		miaoShu: '后退',
		kuaiJieJian: 'KeyS'
	},
	zuoYi: {
		miaoShu: '左移',
		kuaiJieJian: 'KeyA'
	},
	youYi: {
		miaoShu: '右移',
		kuaiJieJian: 'KeyD'
	},
	shangYi: {
		miaoShu: '上移',
		kuaiJieJian: 'KeyR'
	},
	xiaYi: {
		miaoShu: '下移',
		kuaiJieJian: 'KeyF'
	},
	shangZhuan: {
		miaoShu: '上转',
		kuaiJieJian: 'ArrowUp'
	},
	xiaZhuan: {
		miaoShu: '下转',
		kuaiJieJian: 'ArrowDown'
	},
	zuoZhuan: {
		miaoShu: '左转',
		kuaiJieJian: 'ArrowLeft'
	},
	youZhuan: {
		miaoShu: '右转',
		kuaiJieJian: 'ArrowRight'
	},
	zuoXuanZhuan: {
		miaoShu: '左旋转',
		kuaiJieJian: 'KeyQ'
	},
	youXuanZhuan: {
		miaoShu: '右旋转',
		kuaiJieJian: 'KeyE'
	}
}

Object.defineProperty(moRenKuaiJieJian, 'miaoShu', {
	value: '自由视角',
	enumerable: false
})

let moveState = {
	up: 0,
	down: 0,
	left: 0,
	right: 0,
	forward: 0,
	back: 0,
	pitchUp: 0,
	pitchDown: 0,
	yawLeft: 0,
	yawRight: 0,
	rollLeft: 0,
	rollRight: 0
};

let ziYouShiJiao = null

class ZiYouShiJiao extends KongZhi {
	kuaiJieJianBianHao = 'ZiYouShiJiao'
	kuaiJieJian = null
	qiYong = true
	
	constructor() {
		super()
		
		if (sheZhi.kuaiJieJian[this.kuaiJieJianBianHao]) this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] // 从存储中加载快捷键
		else this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] = moRenKuaiJieJian

		this.object = huanJing.camera;
		this.domElement = huanJing.renderer.domElement;

		// API

		this.movementSpeed = 10;
		this.movementSpeedMultiplier = 1
		this.rollSpeed = Math.PI / 12;
		
		this.dragToLook = false
		this.autoForward = false;

		// disable default target object behavior

		// internals

		const scope = this;

		const EPS = 0.000001;

		const lastQuaternion = new Quaternion();
		const lastPosition = new Vector3();

		this.tmpQuaternion = new Quaternion();

		this.status = 0;

		this.moveState = Object.assign({}, moveState)
		this.moveVector = new Vector3(0, 0, 0);
		this.rotationVector = new Vector3(0, 0, 0);

		this.keydown = function(event) {
			if (event.altKey) {
				return;
			}
			let kjj = this.kuaiJieJian
			
			switch (event.code) {

				case kjj.yiSuZeng.kuaiJieJian:
					this.movementSpeedMultiplier *= 10;
					break;
				case kjj.yiSuJian.kuaiJieJian:
					this.movementSpeedMultiplier /= 10;
					break;

				case kjj.qianJin.kuaiJieJian:
					this.moveState.forward = 1;
					break;
				case kjj.houTui.kuaiJieJian:
					this.moveState.back = 1;
					break;

				case kjj.zuoYi.kuaiJieJian:
					this.moveState.left = 1;
					break;
				case kjj.youYi.kuaiJieJian:
					this.moveState.right = 1;
					break;

				case kjj.shangYi.kuaiJieJian:
					this.moveState.up = 1;
					break;
				case kjj.xiaYi.kuaiJieJian:
					this.moveState.down = 1;
					break;

				case kjj.shangZhuan.kuaiJieJian:
					this.moveState.pitchUp = 1;
					break;
				case kjj.xiaZhuan.kuaiJieJian:
					this.moveState.pitchDown = 1;
					break;

				case kjj.zuoZhuan.kuaiJieJian:
					this.moveState.yawLeft = 1;
					break;
				case kjj.youZhuan.kuaiJieJian:
					this.moveState.yawRight = 1;
					break;

				case kjj.zuoXuanZhuan.kuaiJieJian:
					this.moveState.rollLeft = 1;
					break;
				case kjj.youXuanZhuan.kuaiJieJian:
					this.moveState.rollRight = 1;
					break;

			}

			this.updateMovementVector();
			this.updateRotationVector();

		};

		this.keyup = function(event) {
			let kjj = this.kuaiJieJian
			
			switch (event.code) {
				case kjj.qianJin.kuaiJieJian:
					this.moveState.forward = 0;
					break;
				case kjj.houTui.kuaiJieJian:
					this.moveState.back = 0;
					break;

				case kjj.zuoYi.kuaiJieJian:
					this.moveState.left = 0;
					break;
				case kjj.youYi.kuaiJieJian:
					this.moveState.right = 0;
					break;

				case kjj.shangYi.kuaiJieJian:
					this.moveState.up = 0;
					break;
				case kjj.xiaYi.kuaiJieJian:
					this.moveState.down = 0;
					break;

				case kjj.shangZhuan.kuaiJieJian:
					this.moveState.pitchUp = 0;
					break;
				case kjj.xiaZhuan.kuaiJieJian:
					this.moveState.pitchDown = 0;
					break;

				case kjj.zuoZhuan.kuaiJieJian:
					this.moveState.yawLeft = 0;
					break;
				case kjj.youZhuan.kuaiJieJian:
					this.moveState.yawRight = 0;
					break;

				case kjj.zuoXuanZhuan.kuaiJieJian:
					this.moveState.rollLeft = 0;
					break;
				case kjj.youXuanZhuan.kuaiJieJian:
					this.moveState.rollRight = 0;
					break;

			}

			this.updateMovementVector();
			this.updateRotationVector();

		};

		this.pointerdown = function(event) {
			if (!this.qiYong) return

			this.dragToLook = true
		};
		// 浏览器打开控制台时，指针移动卡顿
		this.pointermove = function(event) {
			if (!this.qiYong) return

			if (this.dragToLook) {
				this.moveState.yawLeft = -event.movementX / 2;
				this.moveState.pitchDown = event.movementY / 2;

				this.updateRotationVector();
				this.moveState.yawLeft = this.moveState.pitchDown = 0;
			}

		};

		this.pointerup = function(event) {
			this.dragToLook = false
			this.moveState.yawLeft = this.moveState.pitchDown = 0;
			this.updateRotationVector();
		};

		this.update = function(delta) {
			if (!this.qiYong) return

			if (!KongZhi.kongZhiMuBiao.has(this)) return this.guanBi()
			
			const moveMult = delta * scope.movementSpeed * scope.movementSpeedMultiplier;
			const rotMult = delta * scope.rollSpeed;

			scope.object.translateX(scope.moveVector.x * moveMult);
			scope.object.translateY(scope.moveVector.y * moveMult);
			scope.object.translateZ(scope.moveVector.z * moveMult);

			scope.tmpQuaternion.set(scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1).normalize();
			scope.object.quaternion.multiply(scope.tmpQuaternion);
			// 衰减
			if (scope.dragToLook) {
				scope.rotationVector.x -= scope.rotationVector.x * 10 * delta
				scope.rotationVector.y -= scope.rotationVector.y * 10 * delta
			}

			if (
				lastPosition.distanceToSquared(scope.object.position) > EPS ||
				8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS
			) {

				lastQuaternion.copy(scope.object.quaternion);
				lastPosition.copy(scope.object.position);

			}

		};

		this.updateMovementVector = function() {
			const forward = (this.moveState.forward || (this.autoForward && !this.moveState.back)) ? 1 : 0;

			this.moveVector.x = (-this.moveState.left + this.moveState.right);
			this.moveVector.y = (-this.moveState.down + this.moveState.up);
			this.moveVector.z = (-forward + this.moveState.back);
		};

		this.updateRotationVector = function() {
			this.rotationVector.x = (-this.moveState.pitchDown + this.moveState.pitchUp);
			this.rotationVector.y = (-this.moveState.yawRight + this.moveState.yawLeft);
			this.rotationVector.z = (-this.moveState.rollRight + this.moveState.rollLeft);
		};
		
		this.guanBi = function() {
			this.moveState = Object.assign({}, moveState)
			this.rotationVector.set(0, 0, 0)
		}

		this.updateMovementVector();
		this.updateRotationVector();
		
		ziYouShiJiao = this
	}
	
	chuLi(shiJian) {
		if (shiJian.type == 'keydown') this.keydown(shiJian)
		if (shiJian.type == 'keyup') this.keyup(shiJian)
		if (shiJian.type == 'pointerdown') this.pointerdown(shiJian)
		if (shiJian.type == 'pointerup') this.pointerup(shiJian)
		if (shiJian.type == 'pointermove') this.pointermove(shiJian)
	}
	
	jiaZai() {
		super.jiaZai()
		
		if (document.pointerLockElement) document.exitPointerLock()
		
		// 添加进帧更新
		gengXinJiHe.set(this, this.update.bind(this))
	}
	
	xieZai() {
		super.xieZai()
		
		gengXinJiHe.delete(this)
	}
}

export {
	ZiYouShiJiao,
	ziYouShiJiao
};